﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TakaGUI.DrawBoxes.Forms;
using TakaGUI;
using TakaGUI.Data;
using TakaGUI.DrawBoxes;
using System.Reflection;
using EvoSim;
using EvoApp.Worlds;

namespace EvoApp.Menu.Forms
{
	public class NewSimulationForm : Dialogue
	{
		public Simulation Result;

		TextField fileNameTextField;
		ComboBox worldTypesComboBox;

		IntegerField worldWidthField;
		IntegerField worldHeightField;
		ComboBox worldHasEdgesComboBox;

		IntegerField regionSizeField;
		IntegerField gaussianMinField;
		IntegerField gaussianMaxField;

		ResizableButton okButton;

		List<Type> worldTypeList;
		Dictionary<Type, Dictionary<string, DrawBox>> valueHolders = new Dictionary<Type, Dictionary<string, DrawBox>>();

		public static NewSimulationForm ShowDialog(Window window, CloseEvent closeFunction = null, string category = null, ISkinFile file = null)
		{
			var form = new NewSimulationForm();
			form.Initialize(closeFunction, "New Simulation", true, true, category, file);
			form.Show(window);

			return form;
		}

		public override void AddedToContainer()
		{
			base.AddedToContainer();

			var builder = new FieldBuilder();
			builder.BuildSessionStart(this);

			fileNameTextField = builder.AddBrowseField(FileForm.FileFormTypes.File, FileForm.OperationTypes.Save, "File Directory: ").DrawBox1;

			worldTypesComboBox = builder.AddComboBoxField("World Type: ");
			worldTypeList = new List<Type>();
			{
				var currentAssembly = Assembly.GetExecutingAssembly();
				var assemblyNameList = new List<AssemblyName>();
				assemblyNameList.Add(currentAssembly.GetName());
				assemblyNameList.AddRange(currentAssembly.GetReferencedAssemblies());

				var worldType = typeof(World);

				foreach (var assemblyName in assemblyNameList)
				{
					var assembly = Assembly.Load(assemblyName);
					foreach (var type in assembly.GetTypes())
						if (worldType.IsAssignableFrom(type))
						{
							worldTypeList.Add(type);
							worldTypesComboBox.Items.Add(type.Name);
						}
				}
				worldTypesComboBox.Index = 0;
			}

			worldWidthField = builder.AddIntegerField("World Width: ");
			worldWidthField.MinValue = 1;
			worldHeightField = builder.AddIntegerField("World Height: ");
			worldHeightField.MinValue = 1;
			worldHasEdgesComboBox = builder.AddComboBoxField("World Edges", new List<string> { "Yes", "No" });
			worldHasEdgesComboBox.Index = 0;

			regionSizeField = builder.AddIntegerField("Region Size: ");
			regionSizeField.MinValue = 1;
			regionSizeField.Value = 40;
			gaussianMinField = builder.AddIntegerField("Gassian Generator Min: ");
			gaussianMinField.Value = 0;
			gaussianMaxField = builder.AddIntegerField("Gassian Generator Max: ");
			gaussianMaxField.Value = 1000;

			var switchBox = new SwitchBox();
			switchBox.Initialize();
			builder.AddDrawBoxAsField(switchBox, DrawBoxAlignment.GetLeftRight());
			switchBox.Width = builder.FieldWidth;
			foreach (var type in worldTypeList)
			{
				if (type == typeof(World))
					continue;

				var valueHolder = new Dictionary<string, DrawBox>();
				var panel = (Panel)type.InvokeMember("GUI_CreateNew", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, new[] { valueHolder });
				valueHolders.Add(type, valueHolder);
				
				switchBox.AddDrawBox(panel, type.FullName);
				panel.Alignment = DrawBoxAlignment.GetLeftRight();
			}
			switchBox.HasSwitched += delegate(object sender, DrawBox newSelectedDrawBox)
			{
				if (newSelectedDrawBox != null)
					switchBox.Height = newSelectedDrawBox.Height;
			};
			worldTypesComboBox.SelectedItemChanged += delegate(object sender, int newItemIndex, int oldItemIndex)
			{
				if (worldTypeList[newItemIndex] != typeof(World))
					switchBox.SelectDrawBoxWithKey(worldTypeList[newItemIndex].FullName);
				else
					switchBox.SelectNone();
			};
			switchBox.SelectDrawBoxWithKey(worldTypeList[worldTypesComboBox.Index].FullName);

			okButton = builder.AddResizableButtonField("OK", delegate(object sender)
			{
				Result = new Simulation();
				Result.FileName = fileNameTextField.Text;

				var worldType = worldTypeList[worldTypesComboBox.Index];
				Result.World = (World)Activator.CreateInstance(worldType, (int)regionSizeField.Value, (int)gaussianMinField.Value, (int)gaussianMaxField.Value);

				Result.World.Width = (int)worldWidthField.Value;
				Result.World.Height = (int)worldHeightField.Value;
				Result.World.WorldHasEdges = worldHasEdgesComboBox.CurrentLine == "Yes" ? true : false;

				if (worldType != typeof(World))
					worldType.InvokeMember("GUI_ReadValues", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, Result.World, new[] { valueHolders[worldType] });

				Close();
			}, true);

			int largestHeight = 0;
			foreach (var panel in switchBox.DrawBoxList)
				if (panel.Height > largestHeight)
					largestHeight = panel.Height;

			okButton.Y = switchBox.Y + largestHeight + 6;

			builder.BuildSessionEnd();

			X = (Parent.Width / 2) - (Width / 2);
			Y = (Parent.Height / 2) - (Height / 2);

			CanResizeFormVertically = false;
		}
	}
}
